﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;

namespace DotNetStringsExample
{
    class Program
    {
        static char[][] smallStrings = 
        {
            new char[]{'C',':','\\','P','r','o','g','r','a','m',' ','F','i','l','e','s',' ','(','x','8','6',')','\\','M','i','c','r','o','s','o','f','t',' ','S','D','K','s','\\','W','i','n','d','o','w','s','\\','v','7','.','0','A','\\','I','n','c','l','u','d','e'},
            new char[]{'C',':','\\','P','r','o','g','r','a','m',' ','F','i','l','e','s',' ','(','x','8','6',')','\\','M','i','c','r','o','s','o','f','t',' ','S','D','K','s','\\','W','i','n','d','o','w','s','\\','v','7','.','0','A','\\','l','i','b'},
            new char[]{'C',':','\\','V','S','1','1','\\','V','C','\\','a','t','l','m','f','c','\\','i','n','c','l','u','d','e'},
            new char[]{'C',':','\\','V','S','1','1','\\','V','C','\\','l','i','b'}
        };

        static void StringVectorOfEmptyStringsInitialize()
        {
            List<string> strings = new List<string>();
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            strings.Capacity = 100000;
            for(int i = 0; i < 100000; i++)
            {
                strings.Add(string.Empty);
            }
            stopwatch.Stop();
            Console.Out.WriteLine("List<string> resize(100000): {0}",stopwatch.Elapsed.TotalMilliseconds);
        }

        static void StringVectorInitializeSmallStrings(List<string> v)
        {

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            for (int i = 0; i < 100000; i++)
            {
                v.Add(new string(smallStrings[i % 4]));
            }

            stopwatch.Stop();
            Console.Out.WriteLine("List<string> initialize with small strings: {0}", stopwatch.Elapsed.TotalMilliseconds);
        }


        static void StringVectorGetTotalLength(List<string> v)
        {
            long totalLength = 0;
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            for (int i = 0; i < 100000; i++)
            {
                totalLength += v[i].Length;
            }

            stopwatch.Stop();
            Console.Out.WriteLine("List<string> Get total length ({0}) : {1}", totalLength, stopwatch.Elapsed.TotalMilliseconds);
        }

        static void StringVectorAssignTo(List<string> v, List<string> v2)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            for (int i = 0; i < 100000; i++)
            {
                v2[i] = v[i];
            }

            stopwatch.Stop();
            Console.Out.WriteLine("List<string> assign to: {0}", stopwatch.Elapsed.TotalMilliseconds);
        }

        static void StringVectorInitializeSmallStringsPushBack(List<string> v)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            for(int i = 0; i < 100000; i++)
            {
                v.Add(new string(smallStrings[i%4]) );
            }

            stopwatch.Stop();

            Console.Out.WriteLine("List<string> initialize with small strings Add: {0}", stopwatch.Elapsed.TotalMilliseconds);
        }

        static void StringVectorAppendTo(List<string> v,List<string> v2)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            for(int i = 0; i < 100000; i++)
            {
                v2[i] = v2[i] + v[i];
            }

            stopwatch.Stop();
            Console.Out.WriteLine("List<string> append to: {0}", stopwatch.Elapsed.TotalMilliseconds);
        }


        static void StringVectorAppendCharTo(List<string> v,List<string> v2)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            for(int i = 0; i < 100000; i++)
            {
                var dest = v2[i];
                var destLength = dest.Length;
                var source = v[i];
                var sourceLength = source.Length;
                for(int iii = 0; iii < 10; iii++)
                {
                    for(int ii = 0; ii < sourceLength; ii++)
                    {
                        char c = source[ii];
                        dest += c;
                    }
                }
                v2[i] = dest;
            }

            stopwatch.Stop();
            Console.Out.WriteLine("List<string> append char to: {0}", stopwatch.Elapsed.TotalMilliseconds);
        }

        static void StringVectorSort( List<string> v )
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            v.Sort();

            stopwatch.Stop();
            Console.Out.WriteLine("List<string> sort: {0}", stopwatch.Elapsed.TotalMilliseconds);
        }

        static void StringVectorSimpleIndexOfAnyOf(List<string> v)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            long found = 0;

            foreach(var s in v)
            {
                var pos = s.IndexOfAny(new char[] {'7','b'});
                
                if(pos != -1)
                {
                    found++;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine("List<string> Simple IndexOfAny({0}): {1}", found ,stopwatch.Elapsed.TotalMilliseconds);
        }

        static void StringVectorIndexOfAnyOf(List<string> v)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            long found = 0;
            char[] searchChars = new char[] {'\\','/'};

            foreach (var s in v)
            {
                int pos = -1;
                int start = 0;
                do
                {
                    pos = s.IndexOfAny(searchChars, start);
                    if(pos != -1)
                    {
                        start = pos +1;
                        found++;
                    }

                }while(pos != -1);
            }
            stopwatch.Stop();
            Console.Out.WriteLine("List<string> IndexOfAny({0}): {1}", found, stopwatch.Elapsed.TotalMilliseconds);
        }


        static void StringVectorLastIndexOfAny(List<string> v)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            long found = 0;
            char[] searchChars = new char[] { '\\', '/' };

            foreach (var s in v)
            {
                int pos = -1;
                int start = s.Length-1;
                do
                {
                    pos = s.LastIndexOfAny(searchChars, start);
                    if (pos != -1)
                    {
                        start = pos - 1;
                        found++;
                    }

                } while (pos > 0);
            }
            stopwatch.Stop();
            Console.Out.WriteLine("List<string> LastIndexOfAny({0}): {1}", found, stopwatch.Elapsed.TotalMilliseconds);
        }


        static void StringVectorIndexOf(List<string> v)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            long found = 0;

            foreach (var s in v)
            {
                int pos = -1;
                int start = 0;
                do
                {
                    pos = s.IndexOf("lib", start);
                    if (pos != -1)
                    {
                        start = pos + 1;
                        found++;
                    }

                } while (pos != -1);
            }
            stopwatch.Stop();
            Console.Out.WriteLine("List<string> IndexOf({0}): {1}", found, stopwatch.Elapsed.TotalMilliseconds);
        }

        static void StringVectorLastIndexOf(List<string> v)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            long found = 0;

            foreach (var s in v)
            {
                int pos = -1;
                int start = s.Length - 1;
                do
                {
                    pos = s.LastIndexOf("lib", start);
                    if (pos != -1)
                    {
                        start = pos - 1;
                        found++;
                    }

                } while (pos > 0);
            }
            stopwatch.Stop();
            Console.Out.WriteLine("List<string> LastIndexOf({0}): {1}", found, stopwatch.Elapsed.TotalMilliseconds);
        }


        static void StringVectorInsert(List<string> v)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            

            for (int i = 0; i < 100000; i++)
            {
                v[i] = v[i].Insert(3,"Text");
            }

            stopwatch.Stop();
            Console.Out.WriteLine("List<string> Insert: {0}", stopwatch.Elapsed.TotalMilliseconds);
        }


        static void StringVectorRemove(List<string> v)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();


            for (int i = 0; i < 100000; i++)
            {
                v[i] = v[i].Remove(2, 3);
            }

            stopwatch.Stop();
            Console.Out.WriteLine("List<string> Remove: {0}", stopwatch.Elapsed.TotalMilliseconds);
        }


        const int maxRecursion = 10000;

        static string StringRecursion(string arg,int recursionLevel)
        {
            string result = arg + "Hi";
            if(recursionLevel < maxRecursion)
            {
                recursionLevel++;
                result = StringRecursion(result,recursionLevel);
            }
            return result;
        }

        static void StringRecursion( )
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            string s = "String";

            s = StringRecursion(s,0);

            stopwatch.Stop();
            Console.Out.WriteLine("List<string> recursion: {0}", stopwatch.Elapsed.TotalMilliseconds);
        }


        static void Main(string[] args)
        {
            List<string> strings = new List<string>();
            strings.Capacity = 100000;

            List<string> strings2 = new List<string>();
            strings2.Capacity = 100000;
            for (int i = 0; i < 100000; i++)
            {
                strings2.Add(string.Empty);
            }

            List<string> strings3 = new List<string>();
            strings3.Capacity = 100000;

            List<string> strings4 = new List<string>();
            strings4.Capacity = 100000;
            for (int i = 0; i < 100000; i++)
            {
                strings4.Add(string.Empty);
            }

            StringVectorOfEmptyStringsInitialize();
            StringVectorInitializeSmallStrings(strings);
            StringVectorGetTotalLength(strings);
            StringVectorAssignTo(strings, strings2);
            StringVectorInitializeSmallStringsPushBack(strings3);
            StringVectorAppendTo(strings3, strings4);
            StringVectorAppendCharTo(strings3, strings4);

            StringVectorSort(strings4);
            StringVectorSimpleIndexOfAnyOf(strings4);
            StringVectorIndexOfAnyOf(strings4);
            StringVectorLastIndexOfAny(strings4);
            StringVectorIndexOf(strings4);
            StringVectorLastIndexOf(strings4);
            StringVectorInsert(strings4);
            StringVectorRemove(strings4);

            StringRecursion();



        }
    }
}
